Project in opdracht van NWB projectteam, uitgevoerd door RWS Datalab.
Team:
Martijn Koole - Data Scientist
Daan van der Maas - Data Scientist
Jan Quist - Data Scientist
Steven van Gelder - Product manager
Vikash Rambaran - Product Owner
Onderstaande code importeert alle benodigde libraries en functies en laadt vervolgens de gebruikte data. Er is een uitsnede gemaakt van het NWB Wegvakken bestand van 01-06-2017 rondom Gouda. Vervolgens is een zelfde uitsnede gemaakt voor de Basemap die verkregen is via BeMobile (gebaseerd op Open Street Map, OSM). De uitsnede is in eerste instantie gemaakt om de rekentijd kort te houden tijdens ontwikkelen/testen. Dat gebeurt in het script read_fcd.R. Later kunnen dezelfde scripts gebruikt worden voor om over heel Nederland verschillen te detecteren.
Om het NWB bestand te kunnen vergelijken zullen deze op elkaar gemapt moeten worden. Hiervoor is voor ieder ieder lijnsegment uit de OSM basemap gezocht naar een ‘nearest neighbor’ in het NWB. Met behulp van de afstand tot de nearest neighbor kunnen afwijkingen worden gedetecteerd. Voorbeeld: Objecten in de OSM basemap die geen nearest neighbor in het NWB hebben binnen een bepaalde marge kunnen duiden op missende/onjuiste informatie in het NWB. Andersom (NWB object zonder OSM nearest neighbor) duidt op een weg die wel in NWB bestaat, maar niet in de OSM basemap. Om de afstand te bepalen tussen een object in de OSM basemap en een object in NWB, is gebruik gemaakt van een afgeleide van de Hausdorff distance. Hiervoor is eerst nog enige bewerking gedaan.
#Eerst worden beide shapes omgezet naar RD coordinaten, t.b.v. eenheid meter
rd<- "+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.999908 +x_0=155000 +y_0=463000 +ellps=bessel +units=m +towgs84=565.2369,50.0087,465.658,-0.406857330322398,0.350732676542563,-1.8703473836068,4.0812 +no_defs"
nwb_select<- spTransform(nwb_select,rd)
basemap_select<- spTransform(basemap_select,rd)
Beide bestanden bestaan uit Polyline shapes, maar de OSM basemap heeft een hogere resolutie het NWB (OSM segmenten zijn max 50 m. lang, NWB segmenten vaak langer). Met name bij langere en rechte NWB segmenten (weinig onderliggende punten in de polyline) levert dat problemen op bij het bepalen van de nearest neighbor. Om dat probleem te ondervangen zijn de NWB segmenten eerst kunstmatig opgeknipt in segmenten van max 50 m.
source('prepare_shape.r')
lengte = 25
#Maak NWB equidistant
nwb_select_eq<- nwb_select
x = pblapply( c(1:length(nwb_select@lines)), function(i){
as.data.frame(spacing(pad = nwb_select_eq@lines[[i]]@Lines[[1]]@coords ,lengte= lengte))
})
for(i in 1:length(nwb_select@lines)){
colnames(x[[i]]) = c('x','y')
nwb_select_eq@lines[[i]]@Lines[[1]]@coords = as.matrix(x[[i]])
}
#Maak OSM equidistant
basemap_select_eq<- basemap_select
x = pblapply( c(1:length(basemap_select@lines)), function(i){
spacing(pad = basemap_select_eq@lines[[i]]@Lines[[1]]@coords ,lengte= lengte)
})
for(i in 1:length(basemap_select_eq@lines)){
colnames(x[[i]]) = c('x','y')
basemap_select_eq@lines[[i]]@Lines[[1]]@coords = as.matrix(x[[i]])
}
We berekenen per OSM line en per NWB line de afstand van alle punten op de NWB line tot alle punten of de OSM line. Vervolgens nemen we voor ieder OSM punt de minimale afstand tot de punten op de NWB line. Van deze afstanden nemen we het maximum. Dit noemen we de half-hausdorf afstand tussen de twee lines. Voor idere OSM line matchen we de NWB line met de kleinste half-hausdorf afstand.
basemap_select_eq$segmentID<- as.integer(as.character(basemap_select_eq$segmentID))
source('half_hausdorf.r')
OSM = basemap_select_eq
NWB = nwb_select_eq
distance_lijst_OSM = pblapply(c(1:length(OSM@lines)), function(i){
hausdorf_distances_to_NWB_lines = lapply(c(1:length(NWB@lines)),function(j){
mean_dist(OSM@lines[[i]]@Lines[[1]]@coords, NWB@lines[[j]]@Lines[[1]]@coords )
})
minimum_distance_osm = min(unlist( hausdorf_distances_to_NWB_lines))
label = which.min( unlist(hausdorf_distances_to_NWB_lines) )
return(c(OSM$segmentID[i],as.numeric(as.character(NWB$WVK_ID[label])), minimum_distance_osm))
})
distance_lijst_NWB = pblapply(c(1:length(NWB@lines)), function(i){
hausdorf_distances_to_OSM_lines = lapply(c(1:length(OSM@lines)),function(j){
mean_dist(NWB@lines[[i]]@Lines[[1]]@coords, OSM@lines[[j]]@Lines[[1]]@coords )
})
minimum_distance_nwb = min(unlist( hausdorf_distances_to_NWB_lines))
label = which.min( unlist(hausdorf_distances_to_NWB_lines) )
return(c(NWB$WVK_ID[i],as.numeric(as.character(OSM$segmentID[label])), minimum_distance_nwb))
})
#create df with nearest neighbors
distance_matrix_OSM = as.data.frame(do.call(rbind, distance_lijst_OSM))[,c(1:3)]
colnames(distance_matrix_OSM) = c('OSM_id', 'NWB_id', 'Half_Hausdorfdistance')
#create df with nearest neighbors
distance_matrix_NWB = as.data.frame(do.call(rbind, distance_lijst_NWB))[,c(1:3)]
colnames(distance_matrix_NWB) = c('NWB_id', 'OSM_id', 'Half_Hausdorfdistance')
distance_matrix$ge50<- ifelse(distance_matrix$Half_Hausdorfdistance >=50, TRUE,FALSE) #hh distance greater than or equal to 50 m
#merge
basemap_select$nn_nwb_half<- distance_matrix$NWB_id[match(basemap_select$segmentID,distance_matrix$OSM_id)]
basemap_select$ge50<- distance_matrix$ge50[match(basemap_select$segmentID,distance_matrix$OSM_id)]
basemap_select$hh_dist<- distance_matrix$Half_Hausdorfdistance[match(basemap_select$segmentID,distance_matrix$OSM_id)]
nwb_select$is_nn50<- ifelse(nwb_select$WVK_ID %in% basemap_select$nn_nwb_half[basemap_select$hh_dist<50],TRUE,FALSE )
##back to wgs for plotting
wgs<- "+proj=longlat +ellps=WGS84 +datum=WGS84 +towgs84=0,0,0"
basemap_select_wgs<- spTransform(basemap_select,wgs)
nwb_select_wgs<- spTransform(nwb_select,wgs)
basemap_select_wgs<- basemap_select_wgs[order(basemap_select_wgs$nn_nwb_half),]
nwb_select_wgs<- nwb_select_wgs[order(nwb_select_wgs$WVK_ID),]
#export for shiny
#save(basemap_select_wgs,file="db/basemap_select_wgs.RData")
#save(nwb_select_wgs,file="db/nwb_select_wgs.RData")
#save(distance_matrix,file="db/dist_matrix.RData")
factpal <- colorFactor(c("green","black"), c(TRUE,FALSE))
factpal_nwb <- colorFactor(c("red","blue"), c(TRUE,FALSE))
##leaflet
leaflet() %>% addProviderTiles(providers$CartoDB) %>%
addPolylines(data=nwb_select_wgs,opacity=0.5,col=~factpal_nwb(is_nn50),
popup=~paste("WVK_ID: ",WVK_ID),group="NWB",highlightOptions=highlightOptions(fillOpacity = 1,
bringToFront = TRUE) ) %>%
addPolylines(data=basemap_select_wgs,weight = 5,opacity=0.5,col=~factpal(ge50),group="OSM",
popup= ~paste("SegmentID:",segmentID, "<br>",
"nn_nwb: ",nn_nwb_half, "<br>",
"half_hausdorff: ", hh_dist),highlightOptions=highlightOptions(fillOpacity = 1,
bringToFront = TRUE)) %>%
# Layers control
addLayersControl(
overlayGroups = c("NWB", "OSM"),
options = layersControlOptions(collapsed = FALSE)) %>%
addLegend("bottomright", colors = c("chartreuse","black","blue","red"), labels = c("Wel in OSM, ook in NWB","Wel in OSM, niet NWB",
"Wel in NWB, ook in OSM","Wel in NWB, niet in OSM"),
title = "Legend",
opacity = 0.7)
NA
Vind de juncties en bepaal voor iedere junctie in OSM het dichtsbijzijnde junctie in NWB en andersom
#VUL HIER NIET DE EQUIDISTANTE SHAPE IN MAAR DE ORGINELE SHAPES!
source('vind_juncties.r')
OSM_juncties = vind_juncties(basemap_select)
NWB_juncties = vind_juncties(nwb_select)
dichtst_bijzijnde_NWB_junctie = pblapply(c(1:nrow(OSM_juncties)), function(i){
x = sqrt ( (NWB_juncties[,1] - OSM_juncties[i,1])^2 + (NWB_juncties[,2] - OSM_juncties[i,2])^2 )
x = NWB_juncties[x == min(x),]
return(x[1,])
})
| | 0 % ~calculating
|+ | 1 % ~04s
|+ | 2 % ~04s
|++ | 3 % ~04s
|++ | 4 % ~04s
|+++ | 5 % ~04s
|+++ | 6 % ~04s
|++++ | 7 % ~03s
|++++ | 8 % ~03s
|+++++ | 9 % ~03s
|+++++ | 10% ~03s
|++++++ | 11% ~03s
|++++++ | 12% ~07s
|+++++++ | 13% ~06s
|+++++++ | 14% ~06s
|++++++++ | 15% ~06s
|++++++++ | 16% ~05s
|+++++++++ | 17% ~05s
|+++++++++ | 18% ~05s
|++++++++++ | 19% ~05s
|++++++++++ | 20% ~05s
|+++++++++++ | 21% ~05s
|+++++++++++ | 22% ~04s
|++++++++++++ | 23% ~04s
|++++++++++++ | 24% ~04s
|+++++++++++++ | 25% ~04s
|+++++++++++++ | 26% ~04s
|++++++++++++++ | 27% ~04s
|++++++++++++++ | 28% ~04s
|+++++++++++++++ | 29% ~04s
|+++++++++++++++ | 30% ~04s
|++++++++++++++++ | 31% ~04s
|++++++++++++++++ | 32% ~04s
|+++++++++++++++++ | 33% ~04s
|+++++++++++++++++ | 34% ~04s
|++++++++++++++++++ | 35% ~04s
|++++++++++++++++++ | 36% ~04s
|+++++++++++++++++++ | 37% ~04s
|+++++++++++++++++++ | 38% ~04s
|++++++++++++++++++++ | 39% ~03s
|++++++++++++++++++++ | 40% ~03s
|+++++++++++++++++++++ | 41% ~03s
|+++++++++++++++++++++ | 42% ~03s
|++++++++++++++++++++++ | 43% ~03s
|++++++++++++++++++++++ | 44% ~03s
|+++++++++++++++++++++++ | 45% ~03s
|+++++++++++++++++++++++ | 46% ~03s
|++++++++++++++++++++++++ | 47% ~03s
|++++++++++++++++++++++++ | 48% ~03s
|+++++++++++++++++++++++++ | 49% ~03s
|+++++++++++++++++++++++++ | 50% ~03s
|++++++++++++++++++++++++++ | 51% ~03s
|++++++++++++++++++++++++++ | 52% ~03s
|+++++++++++++++++++++++++++ | 53% ~03s
|+++++++++++++++++++++++++++ | 54% ~03s
|++++++++++++++++++++++++++++ | 55% ~03s
|++++++++++++++++++++++++++++ | 56% ~03s
|+++++++++++++++++++++++++++++ | 57% ~02s
|+++++++++++++++++++++++++++++ | 58% ~02s
|++++++++++++++++++++++++++++++ | 59% ~02s
|++++++++++++++++++++++++++++++ | 60% ~02s
|+++++++++++++++++++++++++++++++ | 61% ~02s
|+++++++++++++++++++++++++++++++ | 62% ~02s
|++++++++++++++++++++++++++++++++ | 63% ~02s
|++++++++++++++++++++++++++++++++ | 64% ~02s
|+++++++++++++++++++++++++++++++++ | 65% ~02s
|+++++++++++++++++++++++++++++++++ | 66% ~02s
|++++++++++++++++++++++++++++++++++ | 67% ~02s
|++++++++++++++++++++++++++++++++++ | 68% ~02s
|+++++++++++++++++++++++++++++++++++ | 69% ~02s
|+++++++++++++++++++++++++++++++++++ | 70% ~02s
|++++++++++++++++++++++++++++++++++++ | 71% ~02s
|++++++++++++++++++++++++++++++++++++ | 72% ~02s
|+++++++++++++++++++++++++++++++++++++ | 73% ~02s
|+++++++++++++++++++++++++++++++++++++ | 74% ~01s
|++++++++++++++++++++++++++++++++++++++ | 75% ~01s
|++++++++++++++++++++++++++++++++++++++ | 76% ~01s
|+++++++++++++++++++++++++++++++++++++++ | 77% ~01s
|+++++++++++++++++++++++++++++++++++++++ | 78% ~01s
|++++++++++++++++++++++++++++++++++++++++ | 79% ~01s
|++++++++++++++++++++++++++++++++++++++++ | 80% ~01s
|+++++++++++++++++++++++++++++++++++++++++ | 81% ~01s
|+++++++++++++++++++++++++++++++++++++++++ | 82% ~01s
|++++++++++++++++++++++++++++++++++++++++++ | 83% ~01s
|++++++++++++++++++++++++++++++++++++++++++ | 84% ~01s
|+++++++++++++++++++++++++++++++++++++++++++ | 85% ~01s
|+++++++++++++++++++++++++++++++++++++++++++ | 86% ~01s
|++++++++++++++++++++++++++++++++++++++++++++ | 87% ~01s
|++++++++++++++++++++++++++++++++++++++++++++ | 88% ~01s
|+++++++++++++++++++++++++++++++++++++++++++++ | 89% ~01s
|+++++++++++++++++++++++++++++++++++++++++++++ | 90% ~01s
|++++++++++++++++++++++++++++++++++++++++++++++ | 91% ~01s
|++++++++++++++++++++++++++++++++++++++++++++++ | 92% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++ | 93% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++ | 94% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 95% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 96% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 06s
dichtst_bijzijnde_NWB_junctie = do.call(rbind, dichtst_bijzijnde_NWB_junctie)
OSM_juncties = cbind(OSM_juncties, dichtst_bijzijnde_NWB_junctie )
colnames(OSM_juncties) = c('x_OSM', 'y_OSM', 'x_NWB', 'y_NWB')
dichtst_bijzijnde_OSM_junctie = pblapply(c(1:nrow(NWB_juncties)), function(i){
x = sqrt ( (OSM_juncties[,1] - NWB_juncties[i,1])^2 + (OSM_juncties[,2] - NWB_juncties[i,2])^2 )
x = OSM_juncties[x == min(x),]
return(x[1,])
})
| | 0 % ~calculating
|+ | 1 % ~02s
|+ | 2 % ~02s
|++ | 3 % ~02s
|++ | 4 % ~02s
|+++ | 5 % ~02s
|+++ | 6 % ~02s
|++++ | 7 % ~02s
|++++ | 8 % ~02s
|+++++ | 9 % ~02s
|+++++ | 10% ~02s
|++++++ | 11% ~02s
|++++++ | 12% ~02s
|+++++++ | 13% ~02s
|+++++++ | 14% ~02s
|++++++++ | 15% ~02s
|++++++++ | 16% ~04s
|+++++++++ | 17% ~03s
|+++++++++ | 18% ~03s
|++++++++++ | 19% ~03s
|++++++++++ | 20% ~03s
|+++++++++++ | 21% ~03s
|+++++++++++ | 22% ~03s
|++++++++++++ | 23% ~03s
|++++++++++++ | 24% ~03s
|+++++++++++++ | 25% ~03s
|+++++++++++++ | 26% ~03s
|++++++++++++++ | 27% ~02s
|++++++++++++++ | 28% ~02s
|+++++++++++++++ | 29% ~02s
|+++++++++++++++ | 30% ~02s
|++++++++++++++++ | 31% ~02s
|++++++++++++++++ | 32% ~03s
|+++++++++++++++++ | 33% ~03s
|+++++++++++++++++ | 34% ~03s
|++++++++++++++++++ | 35% ~03s
|++++++++++++++++++ | 36% ~03s
|+++++++++++++++++++ | 37% ~02s
|+++++++++++++++++++ | 38% ~02s
|++++++++++++++++++++ | 39% ~02s
|++++++++++++++++++++ | 40% ~02s
|+++++++++++++++++++++ | 41% ~02s
|+++++++++++++++++++++ | 42% ~02s
|++++++++++++++++++++++ | 43% ~02s
|++++++++++++++++++++++ | 44% ~02s
|+++++++++++++++++++++++ | 45% ~02s
|+++++++++++++++++++++++ | 46% ~02s
|++++++++++++++++++++++++ | 47% ~02s
|++++++++++++++++++++++++ | 48% ~02s
|+++++++++++++++++++++++++ | 49% ~02s
|+++++++++++++++++++++++++ | 50% ~02s
|++++++++++++++++++++++++++ | 51% ~02s
|++++++++++++++++++++++++++ | 52% ~02s
|+++++++++++++++++++++++++++ | 53% ~02s
|+++++++++++++++++++++++++++ | 54% ~02s
|++++++++++++++++++++++++++++ | 55% ~02s
|++++++++++++++++++++++++++++ | 56% ~02s
|+++++++++++++++++++++++++++++ | 57% ~02s
|+++++++++++++++++++++++++++++ | 58% ~02s
|++++++++++++++++++++++++++++++ | 59% ~02s
|++++++++++++++++++++++++++++++ | 60% ~01s
|+++++++++++++++++++++++++++++++ | 61% ~01s
|+++++++++++++++++++++++++++++++ | 62% ~01s
|++++++++++++++++++++++++++++++++ | 63% ~02s
|++++++++++++++++++++++++++++++++ | 64% ~01s
|+++++++++++++++++++++++++++++++++ | 65% ~01s
|+++++++++++++++++++++++++++++++++ | 66% ~01s
|++++++++++++++++++++++++++++++++++ | 67% ~01s
|++++++++++++++++++++++++++++++++++ | 68% ~01s
|+++++++++++++++++++++++++++++++++++ | 69% ~01s
|+++++++++++++++++++++++++++++++++++ | 70% ~01s
|++++++++++++++++++++++++++++++++++++ | 71% ~01s
|++++++++++++++++++++++++++++++++++++ | 72% ~01s
|+++++++++++++++++++++++++++++++++++++ | 73% ~01s
|+++++++++++++++++++++++++++++++++++++ | 74% ~01s
|++++++++++++++++++++++++++++++++++++++ | 75% ~01s
|++++++++++++++++++++++++++++++++++++++ | 76% ~01s
|+++++++++++++++++++++++++++++++++++++++ | 77% ~01s
|+++++++++++++++++++++++++++++++++++++++ | 78% ~01s
|++++++++++++++++++++++++++++++++++++++++ | 79% ~01s
|++++++++++++++++++++++++++++++++++++++++ | 80% ~01s
|+++++++++++++++++++++++++++++++++++++++++ | 81% ~01s
|+++++++++++++++++++++++++++++++++++++++++ | 82% ~01s
|++++++++++++++++++++++++++++++++++++++++++ | 83% ~01s
|++++++++++++++++++++++++++++++++++++++++++ | 84% ~01s
|+++++++++++++++++++++++++++++++++++++++++++ | 85% ~01s
|+++++++++++++++++++++++++++++++++++++++++++ | 86% ~01s
|++++++++++++++++++++++++++++++++++++++++++++ | 87% ~01s
|++++++++++++++++++++++++++++++++++++++++++++ | 88% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++ | 89% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++ | 90% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++ | 91% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++ | 92% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++ | 93% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++ | 94% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 95% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++ | 96% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++++ | 97% ~00s
|+++++++++++++++++++++++++++++++++++++++++++++++++ | 98% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 99% ~00s
|++++++++++++++++++++++++++++++++++++++++++++++++++| 100% elapsed = 04s
dichtst_bijzijnde_OSM_junctie = do.call(rbind, dichtst_bijzijnde_OSM_junctie)
NWB_juncties = cbind(dichtst_bijzijnde_NWB_junctie , OSM_juncties )
colnames(NWB_juncties) = c('x_NWB', 'y_NWB', 'x_OSM', 'y_OSM')
Vind voor alle punten op een NWB segment de dichtsbijzijnde punten van OSM. Kijk of het maximum en het gemiddelde niet tever afwijken.
#GEBRUIK NU WEL EQUIDISTANTE SHAPES
#zet alle punten van OSM in een dataframe
points_OSM = pblapply(c(1:length(OSM@lines)), function(i){
as.data.frame(OSM@lines[[i]]@Lines[[1]]@coords)
})
points_OSM = rbindlist(points_OSM)
points_OSM = points_OSM[!duplicated(points_OSM),]
#zet alle punten van het NWB in een dataframe
points_NWB = pblapply(c(1:length(NWB@lines)), function(i){
as.data.frame(NWB@lines[[i]]@Lines[[1]]@coords)
})
points_NWB = rbindlist(points_NWB)
points_NWB = points_NWB[!duplicated(points_NWB),]
#bereken de nearest neighbour afstand voor ieder punt in het nwb ten opzichten van de punten in het OSM
NWB_to_OSM_points = pblapply(c(1:nrow(points_NWB)) , function(i){
distances = sqrt( ( points_OSM[,1] - as.numeric(points_NWB[i,1]) )^2 + ( points_OSM[,2] - as.numeric(points_NWB[i,2]) )^2 )
return( min(distances))
})
drempel = 30
locaties_fouten = points_NWB[unlist(NWB_to_OSM_points) > drempel ,]
Dit stuk code leest alle tabellen van de floatin car data en maakt er een tabel van met 4 kolommen. Het wegsegment ID, de gemiddeld gereden snelheid, het aantal tabellen waarin het segement voorkomt en de cummulatieve intensiteit. Deze tabel word gemaakt voor 6-19 en 19-6 om rekening te houden met wisseling in maximum snelheid.
tabel_overdag = merge_tables(dir = dir,uur1 = uur1, uur2 = uur2)
Er komen soms kleine onterechte aftakkingen voor in het NWB om die op te kunnen sporen vergelijken we expleciet de doodlopende wegen van het NWB met het OSM.
rand = data.frame('x'= -1, 'y' = -1)
for(i in 1:length(nwb_select@lines)){
nieuw = nwb_select@lines[[i]]@Lines[[1]]@coords
colnames(nieuw) = c('x','y')
rand_nieuw = rbind(nieuw[1,] ,nieuw[nrow(nieuw),])
rand = rbind(rand, rand_nieuw)
}
rand = rand[-1,]
doodlopend_nwb = rand[!duplicated(rand),]
rand = data.frame('x'= -1, 'y' = -1)
for(i in 1:length(basemap_select@lines)){
nieuw = basemap_select@lines[[i]]@Lines[[1]]@coords
colnames(nieuw) = c('x','y')
rand_nieuw = rbind(nieuw[1,] ,nieuw[nrow(nieuw),])
rand = rbind(rand, rand_nieuw)
}
rand = rand[-1,]
doodlopend_osm = rand[!duplicated(rand),]